package cn.zhonghuanzhiyuan.sprc.common.utils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

/**
 * @author whongyu
 * @Description: 时间字段工具类
 * @date 2016/10/9
 */
public class DateUtil {

    public static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public static final String DEFAULT_REGULAR = "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s((([0-1][0-9])|(2?[0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$";

    public static final String CRAWLER_FORMAT = "yyyy/MM/dd HH:mm:ss";

    public static final String SOLR_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    public static final String DATE_FORMAT = "yyyy-MM-dd";

    public static final String MINUTE_FORMAT = "yyyy-MM-dd HH:mm";

    public static final String SHORT_DATE_FORMAT = "yyMMdd";

    private static Calendar cal = Calendar.getInstance();

    public static final String DATE_FORMAT_NO_HYPHONE = "yyyyMMdd";

    public static final String START_FORMAT = "yyyy-MM-dd 00:00:00";

    public static final String DATE_NIAN_YU_RI_FORMART = "yyyy年MM月dd日";

    public static final String NO_FORMAT = "yyyyMMddHHmmss";


    /**
     * 解析时间 将字符串转为时间
     *
     * @param srcDate
     * @return
     * @throws ParseException
     */
    public static Date parse(String srcDate) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_FORMAT);
        Date date = null;
        try {
            date = sdf.parse(srcDate);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return date;
    }

    /**
     * 解析时间 将时间转为字符串
     *
     * @param srcDate
     * @return
     * @throws ParseException
     */
    public static String parse(Date srcDate) {
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_FORMAT);
        String date = null;
        try {
            date = sdf.format(srcDate);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return date;
    }

    /**
     * 解析时间  yyyy-MM-dd 格式
     *
     * @param srcDate
     * @return
     * @throws ParseException
     */
    public static Date parseDate(String srcDate) {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
        Date date = null;
        try {
            date = sdf.parse(srcDate);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return date;
    }

    /**
     * 获取当前时间 年月日 时分秒
     *
     * @return String
     */
    public static String getNowDateTime() {
        return format(new Date());
    }

    /**
     * 根据传入的格式进行转换
     *
     * @param srcDate
     * @param format
     * @return
     */
    public static Date parseDate(String srcDate, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = sdf.parse(srcDate);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return date;
    }

    /**
     * 格式化时间
     *
     * @param srcDate
     * @param srcFormat
     * @param destFormat
     * @return
     */
    public static String format(String srcDate, String srcFormat, String destFormat) {
        SimpleDateFormat src = new SimpleDateFormat(srcFormat);
        Date date = null;
        try {
            date = src.parse(srcDate);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        return format(date, destFormat);
    }

    /**
     * 格式化时间
     *
     * @param date
     * @return
     */
    public static String format(Date date) {
        return format(date, DEFAULT_FORMAT);
    }


    /**
     * 将CST格式转换为默认时间格式
     *
     * @param cstDate
     * @return
     * @throws ParseException
     */
    public static String cstToDefault(String cstDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US);
        try {
            return format(sdf.parse(cstDate), DEFAULT_FORMAT);
        } catch (ParseException e) {
            throw new RuntimeException("输入时间'" + cstDate + "'格式不正确，时间格式应为EEE MMM dd HH:mm:ss zzz yyyy", e);
        }
    }

    /**
     * 转换默认格式为指定时间格式
     *
     * @param date
     * @param format
     * @return
     */
    public static String format(Object date, String format) {

        if (date == null)
            return null;
        if ("".equals(date))
            return "";

        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 格式化开始时间
     *
     * @param srcDate
     * @return
     */
    public static String formatStart(Object srcDate) {
        return completeDate(srcDate, true);
    }

    /**
     * 格式化结束时间
     *
     * @param srcDate
     * @return
     */
    public static String formatEnd(Object srcDate) {
        return completeDate(srcDate, false);
    }

    /**
     * 补全时间
     *
     * @param srcDate
     * @param isStart
     * @return
     */
    public static String completeDate(Object srcDate, boolean isStart) {
        if (srcDate == null)
            return null;
        if ("".equals(srcDate))
            return "";

        String tmpDate = srcDate.toString();
        if (tmpDate.length() != 10)
            return tmpDate;

        if (isStart) {
            return srcDate + " 00:00:00";
        } else {
            return srcDate + " 23:59:59";
        }
    }

    /**
     * 获取上年时间
     *
     * @param srcDate
     * @return
     */
    public static String getLastYear(String srcDate) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");

        Calendar theCa = Calendar.getInstance();
        try {
            theCa.setTime(sdf.parse(srcDate));
        } catch (ParseException e) {

        }
        theCa.add(theCa.YEAR, -1);
        return sdf.format(theCa.getTime());
    }

    /**
     * 转化 z时间格式转换 TUC
     *
     * @param time
     * @return
     */
    public static String getDateFormat(String time) {
        time = time.replace("Z", " UTC");//UTC是本地时间
        SimpleDateFormat format = new SimpleDateFormat(SOLR_FORMAT);
        Date d = null;
        try {
            d = format.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        String date = sf.format(d);
        return date;
    }

    public static String formatDate(Date date) {
//        System.out.println(format(date, DATE_FORMAT));
        return format(date, DATE_FORMAT);
    }

    public static String formatShortYearDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(SHORT_DATE_FORMAT);
        return sdf.format(date);
    }


    //获取本月的开始时间
    public static Date getBeginDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 1, 1);
        return getDayStartTime(calendar.getTime());
    }

    //获取某个日期的开始时间
    public static Timestamp getDayStartTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d) calendar.setTime(d);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return new Timestamp(calendar.getTimeInMillis());
    }

    //获取今年是哪一年
    public static Integer getNowYear() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return Integer.valueOf(gc.get(1));
    }

    //获取本月是哪一月
    public static int getNowMonth() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return gc.get(2) + 1;
    }

    public static Integer getNowHour() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return Integer.valueOf(gc.get(Calendar.HOUR_OF_DAY));
    }
    /**
     * 根据周数获取日期范围
     *
     * @param week
     * @return
     */
    public static String getWeekDays(Integer week) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy");
        Date date = new Date();
        String year = sdf1.format(date);
        cal.set(Calendar.YEAR, Integer.valueOf(year));
        cal.set(Calendar.WEEK_OF_YEAR, week);
        cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
        String beginDate = sdf.format(cal.getTime());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        String endDate = sdf.format(cal.getTime());
        return beginDate + "至" + endDate;
    }

    /**
     * 获取当前周的周一的日期
     *
     * @param date 传入当前日期
     * @return
     */
    public static Date getThisWeekMonday(Date date) {

        cal.setTime(date);
        // 获得当前日期是一个星期的第几天
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        // 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        // 获得当前日期是一个星期的第几天
        int day = cal.get(Calendar.DAY_OF_WEEK);
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);
        return cal.getTime();
    }

    //获取当前时间精确到毫秒 年月日时分秒毫秒
    public static String getNowDateSSS() {
        return new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
    }

    //获取当前周的周一
    public static String getThisWeekOne(int num) {
        cal.setTime(new Date());
        cal.setFirstDayOfWeek(Calendar.MONDAY);
        return new SimpleDateFormat("MM-dd").format(getThisWeekMonday(cal.getTime()));
    }

    //获取当前周的周日
    public static String getThisWeekSeven(int num) {
        cal.setTime(new Date());
        cal.add(Calendar.DATE, num);
        return new SimpleDateFormat("MM-dd").format(getThisWeekMonday(cal.getTime()));
    }

    /*
     判读时间差距，两个时间相差多少天
     */
    public static long getDiffDay(String date) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        long days = 0;
        try {
            Date currentTime = dateFormat.parse(dateFormat.format(new Date()));//现在系统当前时间
            Date pastTime = dateFormat.parse(date);//过去时间
            long diff = currentTime.getTime() - pastTime.getTime();
            days = diff / (1000 * 60 * 60 * 24);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (days < 0) {
            days = 0;
        }
        return days;
    }

    /**
     * 日期格式字符串转时间戳转换成
     *
     * @param dateStr yyyy-MM-dd HH:mm:ss 字符串
     * @return
     */
    public static Long date2TimeStamp(String dateStr) throws ParseException {
        if (dateStr == null || dateStr.isEmpty() || dateStr.equals("null")) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_FORMAT);
        Date date = sdf.parse(dateStr);
        return date.getTime() / 1000L;
    }

    /**
     * 获取指定时间下一天的23:59:59 日期  例如 today =  2020-01-01 12:20:36 则返回值为 2020-01-02 12:20:36
     *
     * @param today
     * @return
     */
    public static Date getNextDayDate(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    public static String dateToISO8610String(Date date) {
        return df.format(date);
    }

    public static final String ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
    private static final SimpleDateFormat df = new SimpleDateFormat(ISO8601_DATE_FORMAT);
    public static final String ISO8601_DATE_FORMAT_WITHMS = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
    private static final SimpleDateFormat df_withms = new SimpleDateFormat(ISO8601_DATE_FORMAT_WITHMS);

    public static SimpleDateFormat getISO8601DateFormat() {
        return df;
    }

    public static Date ISO8610StringToDate(String s) throws ParseException {
        try {
            return df.parse(s);
        } catch (Exception e) {
            return df_withms.parse(s);
        }
    }

    public static String formatTimeToMinute(Long ms) {
        return formatTimeToMinute(ms, true, true, true, true);
    }

    public static String formatTimeToMinute(Long ms, boolean hourPrecision, boolean minutePrecision, boolean secondPrecision, boolean milliSecondPrecision) {
        if (ms == null) return null;
        Integer ss = 1000;
        Integer mi = ss * 60;
        Integer hh = mi * 60;
        Integer dd = hh * 24;

        Long day = ms / dd;
        Long hour = (ms - day * dd) / hh;
        Long minute = (ms - day * dd - hour * hh) / mi;
        Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
        Long milliSecond = ms % ss;

        StringBuffer sb = new StringBuffer();
        if (day > 0) {
            sb.append(day + "天");
        }
        if (hour > 0 && hourPrecision) {
            sb.append(hour + "小时");
        }
        if (minute > 0  && minutePrecision) {
            sb.append(minute + "分");
        }
        if ((second > 0  || (second == 0 && milliSecond == 0)) && secondPrecision) {
            sb.append(second + "秒");
        }
        if (milliSecond > 0 && milliSecondPrecision) {
            sb.append(milliSecond + "毫秒");
        }
        return sb.toString();
    }

    public static Date getDateStartTime(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date getDateEndTime(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    /**
     * 得到指定日期的下一个整点时间
     * @param date
     * @return
     */
    public static Date getNextHour(Date date) {
        return getHourOffset(date, 1, true);
    }

    /**
     * 计算指定时间在指定偏移量后的时间
     * @param date
     * @param offset
     * @return
     */
    public static Date getHourOffset(Date date, int offset) {
        return getHourOffset(date, offset, false);
    }

    public static Date getHourOffset(Date date, int offset, boolean isIntegral) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.HOUR, offset);
        if(isIntegral){
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MILLISECOND, 0);
        }
        return cal.getTime();
    }
}
